home *** CD-ROM | disk | FTP | other *** search
/ Windows Game Programming for Dummies (2nd Edition) / WinGamProgFD.iso / pc / DirectX SDK / DXSDK / samples / Multimedia / DirectShow / BaseClasses / cprop.cpp < prev    next >
Encoding:
C/C++ Source or Header  |  2001-10-08  |  10.2 KB  |  381 lines

  1. //------------------------------------------------------------------------------
  2. // File: CProp.cpp
  3. //
  4. // Desc: DirectShow base classes - implements CBasePropertyPage class.
  5. //
  6. // Copyright (c) 1992-2001 Microsoft Corporation.  All rights reserved.
  7. //------------------------------------------------------------------------------
  8.  
  9.  
  10. #include <streams.h>
  11.  
  12. // Constructor for the base property page class. As described in the header
  13. // file we must be initialised with dialog and title resource identifiers.
  14. // The class supports IPropertyPage and overrides AddRef and Release calls
  15. // to keep track of the reference counts. When the last count is released
  16. // we call SetPageSite(NULL) and SetObjects(0,NULL) to release interfaces
  17. // previously obtained by the property page when it had SetObjects called
  18.  
  19. CBasePropertyPage::CBasePropertyPage(TCHAR *pName,      // Debug only name
  20.                                      LPUNKNOWN pUnk,    // COM Delegator
  21.                                      int DialogId,      // Resource ID
  22.                                      int TitleId) :     // To get tital
  23.     CUnknown(pName,pUnk),
  24.     m_DialogId(DialogId),
  25.     m_TitleId(TitleId),
  26.     m_hwnd(NULL),
  27.     m_Dlg(NULL),
  28.     m_pPageSite(NULL),
  29.     m_bObjectSet(FALSE),
  30.     m_bDirty(FALSE)
  31. {
  32. }
  33.  
  34. #ifdef UNICODE
  35. CBasePropertyPage::CBasePropertyPage(CHAR *pName,      // Debug only name
  36.                                      LPUNKNOWN pUnk,    // COM Delegator
  37.                                      int DialogId,      // Resource ID
  38.                                      int TitleId) :     // To get tital
  39.     CUnknown(pName,pUnk),
  40.     m_DialogId(DialogId),
  41.     m_TitleId(TitleId),
  42.     m_hwnd(NULL),
  43.     m_Dlg(NULL),
  44.     m_pPageSite(NULL),
  45.     m_bObjectSet(FALSE),
  46.     m_bDirty(FALSE)
  47. {
  48. }
  49. #endif
  50.  
  51. // Increment our reference count
  52.  
  53. STDMETHODIMP_(ULONG) CBasePropertyPage::NonDelegatingAddRef()
  54. {
  55.     LONG lRef = InterlockedIncrement(&m_cRef);
  56.     ASSERT(lRef > 0);
  57.     return max(ULONG(m_cRef),1ul);
  58. }
  59.  
  60.  
  61. // Release a reference count and protect against reentrancy
  62.  
  63. STDMETHODIMP_(ULONG) CBasePropertyPage::NonDelegatingRelease()
  64. {
  65.     // If the reference count drops to zero delete ourselves
  66.  
  67.     if (InterlockedDecrement(&m_cRef) == 0) {
  68.         m_cRef++;
  69.         SetPageSite(NULL);
  70.         SetObjects(0,NULL);
  71.         delete this;
  72.         return ULONG(0);
  73.     } else {
  74.         return max(ULONG(m_cRef),1ul);
  75.     }
  76. }
  77.  
  78.  
  79. // Expose our IPropertyPage interface
  80.  
  81. STDMETHODIMP
  82. CBasePropertyPage::NonDelegatingQueryInterface(REFIID riid,void **ppv)
  83. {
  84.     if (riid == IID_IPropertyPage) {
  85.         return GetInterface((IPropertyPage *)this,ppv);
  86.     } else {
  87.         return CUnknown::NonDelegatingQueryInterface(riid,ppv);
  88.     }
  89. }
  90.  
  91.  
  92. // Get the page info so that the page site can size itself
  93.  
  94. STDMETHODIMP CBasePropertyPage::GetPageInfo(LPPROPPAGEINFO pPageInfo)
  95. {
  96.     CheckPointer(pPageInfo,E_POINTER);
  97.     WCHAR wszTitle[STR_MAX_LENGTH];
  98.     WideStringFromResource(wszTitle,m_TitleId);
  99.  
  100.     // Allocate dynamic memory for the property page title
  101.  
  102.     LPOLESTR pszTitle;
  103.     HRESULT hr = AMGetWideString(wszTitle, &pszTitle);
  104.     if (FAILED(hr)) {
  105.         NOTE("No caption memory");
  106.         return hr;
  107.     }
  108.  
  109.     pPageInfo->cb               = sizeof(PROPPAGEINFO);
  110.     pPageInfo->pszTitle         = pszTitle;
  111.     pPageInfo->pszDocString     = NULL;
  112.     pPageInfo->pszHelpFile      = NULL;
  113.     pPageInfo->dwHelpContext    = 0;
  114.  
  115.     // Set defaults in case GetDialogSize fails
  116.     pPageInfo->size.cx          = 340;
  117.     pPageInfo->size.cy          = 150;
  118.  
  119.     GetDialogSize(m_DialogId, DialogProc,0L,&pPageInfo->size);
  120.     return NOERROR;
  121. }
  122.  
  123.  
  124. // Handles the messages for our property window
  125.  
  126. INT_PTR CALLBACK CBasePropertyPage::DialogProc(HWND hwnd,
  127.                                             UINT uMsg,
  128.                                             WPARAM wParam,
  129.                                             LPARAM lParam)
  130. {
  131.     CBasePropertyPage *pPropertyPage;
  132.  
  133.     switch (uMsg) {
  134.  
  135.         case WM_INITDIALOG:
  136.  
  137.             SetWindowLongPtr(hwnd, DWLP_USER, lParam);
  138.  
  139.             // This pointer may be NULL when calculating size
  140.  
  141.             pPropertyPage = (CBasePropertyPage *) lParam;
  142.             if (pPropertyPage == NULL) {
  143.                 return (LRESULT) 1;
  144.             }
  145.             pPropertyPage->m_Dlg = hwnd;
  146.     }
  147.  
  148.     // This pointer may be NULL when calculating size
  149.  
  150.     pPropertyPage = (CBasePropertyPage *) GetWindowLongPtr(hwnd, DWLP_USER);
  151.     if (pPropertyPage == NULL) {
  152.         return (LRESULT) 1;
  153.     }
  154.     return pPropertyPage->OnReceiveMessage(hwnd,uMsg,wParam,lParam);
  155. }
  156.  
  157.  
  158. // Tells us the object that should be informed of the property changes
  159.  
  160. STDMETHODIMP CBasePropertyPage::SetObjects(ULONG cObjects,LPUNKNOWN *ppUnk)
  161. {
  162.     if (cObjects == 1) {
  163.  
  164.         if ((ppUnk == NULL) || (*ppUnk == NULL)) {
  165.             return E_POINTER;
  166.         }
  167.  
  168.         // Set a flag to say that we have set the Object
  169.         m_bObjectSet = TRUE ;
  170.         return OnConnect(*ppUnk);
  171.  
  172.     } else if (cObjects == 0) {
  173.  
  174.         // Set a flag to say that we have not set the Object for the page
  175.         m_bObjectSet = FALSE ;
  176.         return OnDisconnect();
  177.     }
  178.  
  179.     DbgBreak("No support for more than one object");
  180.     return E_UNEXPECTED;
  181. }
  182.  
  183.  
  184. // Create the window we will use to edit properties
  185.  
  186. STDMETHODIMP CBasePropertyPage::Activate(HWND hwndParent,
  187.                                          LPCRECT pRect,
  188.                                          BOOL fModal)
  189. {
  190.     CheckPointer(pRect,E_POINTER);
  191.  
  192.     // Return failure if SetObject has not been called.
  193.     if (m_bObjectSet == FALSE) {
  194.         return E_UNEXPECTED;
  195.     }
  196.  
  197.     if (m_hwnd) {
  198.         return E_UNEXPECTED;
  199.     }
  200.  
  201.     m_hwnd = CreateDialogParam(g_hInst,
  202.                                MAKEINTRESOURCE(m_DialogId),
  203.                                hwndParent,
  204.                                DialogProc,
  205.                                (LPARAM) this);
  206.     if (m_hwnd == NULL) {
  207.         return E_OUTOFMEMORY;
  208.     }
  209.  
  210.     OnActivate();
  211.     Move(pRect);
  212.     return Show(SW_SHOWNORMAL);
  213. }
  214.  
  215.  
  216. // Set the position of the property page
  217.  
  218. STDMETHODIMP CBasePropertyPage::Move(LPCRECT pRect)
  219. {
  220.     CheckPointer(pRect,E_POINTER);
  221.  
  222.     if (m_hwnd == NULL) {
  223.         return E_UNEXPECTED;
  224.     }
  225.  
  226.     MoveWindow(m_hwnd,              // Property page handle
  227.                pRect->left,         // x coordinate
  228.                pRect->top,          // y coordinate
  229.                WIDTH(pRect),        // Overall window width
  230.                HEIGHT(pRect),       // And likewise height
  231.                TRUE);               // Should we repaint it
  232.  
  233.     return NOERROR;
  234. }
  235.  
  236.  
  237. // Display the property dialog
  238.  
  239. STDMETHODIMP CBasePropertyPage::Show(UINT nCmdShow)
  240. {
  241.    // Have we been activated yet
  242.  
  243.     if (m_hwnd == NULL) {
  244.         return E_UNEXPECTED;
  245.     }
  246.  
  247.     // Ignore wrong show flags
  248.  
  249.     if ((nCmdShow != SW_SHOW) && (nCmdShow != SW_SHOWNORMAL) && (nCmdShow != SW_HIDE)) {
  250.         return E_INVALIDARG;
  251.     }
  252.  
  253.     ShowWindow(m_hwnd,nCmdShow);
  254.     InvalidateRect(m_hwnd,NULL,TRUE);
  255.     return NOERROR;
  256. }
  257.  
  258.  
  259. // Destroy the property page dialog
  260.  
  261. STDMETHODIMP CBasePropertyPage::Deactivate(void)
  262. {
  263.     if (m_hwnd == NULL) {
  264.         return E_UNEXPECTED;
  265.     }
  266.  
  267.     // Remove WS_EX_CONTROLPARENT before DestroyWindow call
  268.  
  269.     DWORD dwStyle = GetWindowLong(m_hwnd, GWL_EXSTYLE);
  270.     dwStyle = dwStyle & (~WS_EX_CONTROLPARENT);
  271.  
  272.     //  Set m_hwnd to be NULL temporarily so the message handler
  273.     //  for WM_STYLECHANGING doesn't add the WS_EX_CONTROLPARENT
  274.     //  style back in
  275.     HWND hwnd = m_hwnd;
  276.     m_hwnd = NULL;
  277.     SetWindowLong(hwnd, GWL_EXSTYLE, dwStyle);
  278.     m_hwnd = hwnd;
  279.  
  280.     OnDeactivate();
  281.  
  282.     // Destroy the dialog window
  283.  
  284.     DestroyWindow(m_hwnd);
  285.     m_hwnd = NULL;
  286.     return NOERROR;
  287. }
  288.  
  289.  
  290. // Tells the application property page site
  291.  
  292. STDMETHODIMP CBasePropertyPage::SetPageSite(LPPROPERTYPAGESITE pPageSite)
  293. {
  294.     if (pPageSite) {
  295.  
  296.         if (m_pPageSite) {
  297.             return E_UNEXPECTED;
  298.         }
  299.  
  300.         m_pPageSite = pPageSite;
  301.         m_pPageSite->AddRef();
  302.  
  303.     } else {
  304.  
  305.         if (m_pPageSite == NULL) {
  306.             return E_UNEXPECTED;
  307.         }
  308.  
  309.         m_pPageSite->Release();
  310.         m_pPageSite = NULL;
  311.     }
  312.     return NOERROR;
  313. }
  314.  
  315.  
  316. // Apply any changes so far made
  317.  
  318. STDMETHODIMP CBasePropertyPage::Apply()
  319. {
  320.     // In ActiveMovie 1.0 we used to check whether we had been activated or
  321.     // not. This is too constrictive. Apply should be allowed as long as
  322.     // SetObject was called to set an object. So we will no longer check to
  323.     // see if we have been activated (ie., m_hWnd != NULL), but instead
  324.     // make sure that m_bObjectSet is TRUE (ie., SetObject has been called).
  325.  
  326.     if (m_bObjectSet == FALSE) {
  327.         return E_UNEXPECTED;
  328.     }
  329.  
  330.     // Must have had a site set
  331.  
  332.     if (m_pPageSite == NULL) {
  333.         return E_UNEXPECTED;
  334.     }
  335.  
  336.     // Has anything changed
  337.  
  338.     if (m_bDirty == FALSE) {
  339.         return NOERROR;
  340.     }
  341.  
  342.     // Commit derived class changes
  343.  
  344.     HRESULT hr = OnApplyChanges();
  345.     if (SUCCEEDED(hr)) {
  346.         m_bDirty = FALSE;
  347.     }
  348.     return hr;
  349. }
  350.  
  351.  
  352. // Base class definition for message handling
  353.  
  354. INT_PTR CBasePropertyPage::OnReceiveMessage(HWND hwnd,UINT uMsg,WPARAM wParam,LPARAM lParam)
  355. {
  356.     // we would like the TAB key to move around the tab stops in our property
  357.     // page, but for some reason OleCreatePropertyFrame clears the CONTROLPARENT
  358.     // style behind our back, so we need to switch it back on now behind its
  359.     // back.  Otherwise the tab key will be useless in every page.
  360.     //
  361.  
  362.     CBasePropertyPage *pPropertyPage;
  363.     {
  364.         pPropertyPage = (CBasePropertyPage *) GetWindowLongPtr(hwnd, DWLP_USER);
  365.         if (pPropertyPage->m_hwnd == NULL) {
  366.             return 0;
  367.         }
  368.         switch (uMsg) {
  369.           case WM_STYLECHANGING:
  370.               if (wParam == GWL_EXSTYLE) {
  371.                   LPSTYLESTRUCT lpss = (LPSTYLESTRUCT)lParam;
  372.                   lpss->styleNew |= WS_EX_CONTROLPARENT;
  373.                   return 0;
  374.               }
  375.         }
  376.     }
  377.         
  378.     return DefWindowProc(hwnd,uMsg,wParam,lParam);
  379. }
  380.  
  381.